#include "GLVertexBuffer.h"

#include "GL.h"
#include "GLArrayBuffer.h"
#include "../../IRenderDevice.h"

namespace Rz { namespace Graphics { namespace Render { namespace Libraries { namespace OpenGL {

GLVertexBuffer::GLVertexBuffer(IRenderDevice* renderDevice)
	: GLArrayBuffer(renderDevice, BufferObjectType::VertexBuffer)
{

}

GLVertexBuffer::~GLVertexBuffer()
{

}

void GLVertexBuffer::Bind()
{
	GLArrayBuffer::Bind();

	// Apply vertex description
	auto& elements = this->GetVertexDescription()->GetVertexElements();
	GLsizei stride = static_cast<GLsizei>(this->GetVertexDescription()->GetVertexStride());
	u32 counter = 0;

	for (auto& e : elements)
	{
		// REVIEW: GLShaderAttribute?
		GL::EnableVertexAttribArray(counter);

		GLenum type = GL_FLOAT;
		GLint size;
		bool normalized = false;
		VertexElementUsageToSize(e.GetVertexElementUsage(), &type, &size, &normalized);

		GL::VertexAttribPointer(counter,
			size,
			type,
			normalized,
			stride,
			reinterpret_cast<const GLvoid*>(e.GetOffset()));

		counter++;
	}
}

void GLVertexBuffer::Unbind()
{

}

void GLVertexBuffer::VertexElementUsageToSize(VertexElementUsage usage, GLenum* type, GLint* size, bool* normalized)
{
	switch (usage)
	{
		case VertexElementUsage::Binormal:
		case VertexElementUsage::Normal:
		case VertexElementUsage::Tangent:
		case VertexElementUsage::BlendIndices:
		case VertexElementUsage::BlendWeight:
		case VertexElementUsage::Position:
			*size = 3;
			break;

		case VertexElementUsage::Color:
			*size = 4;
			*type = GL_UNSIGNED_BYTE;
			*normalized = true;
			break;

		case VertexElementUsage::TextureCoordinate:
			*size = 2;
			break;

		case VertexElementUsage::Fog:
		case VertexElementUsage::PointSize:
		case VertexElementUsage::TessellateFactor:
			*size = 1;
			break;

		// TODO
		default:
		case VertexElementUsage::Depth:
		case VertexElementUsage::Sample:
			*size = 4;
			break;
	}
}

} } } } }
